package com.pucong.gitee.database.backup.utils;

import com.pucong.gitee.database.backup.configuration.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
public class FileUtil {

    /**
     * 附件上传
     *
     * @param file
     */
    public static Boolean uploadFile(MultipartFile file, String uploadPath) {
        if (file.isEmpty()) {
            throw new BusinessException("附件为空");
        }
        File uploadFile = new File(uploadPath);
        if (!uploadFile.getParentFile().getParentFile().exists()) {
            uploadFile.getParentFile().getParentFile().mkdirs();
        }
        if (!uploadFile.getParentFile().exists()) {
            uploadFile.getParentFile().mkdirs();
        }
        try {
            if (!uploadFile.exists()) {
                uploadFile.createNewFile();
            }
            file.transferTo(uploadFile);
        } catch (IOException e) {
            log.error("上传附件失败", e);
            throw new BusinessException("上传失败");
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     */
    public static Boolean deleteFile(String path) {
        File file = new File(path);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                log.info("删除单个文件" + path + "成功！");
                return true;
            } else {
                log.error("删除单个文件" + path + "失败！");
                return false;
            }
        } else {
            log.error("删除单个文件失败：" + path + "不存在！");
            return false;
        }
    }

    public static void downLoadFile(String path, String fileName, HttpServletResponse response) {
        if (StringUtils.isBlank(path)) {
            throw new BusinessException("传入参数错误");
        }
        File file = new File(path);
        //当文件存在
        if (file.exists()) {
            response.reset();
            //首先设置响应的内容格式是force-download，那么你一旦点击下载按钮就会自动下载文件了
            response.setContentType("application/force-download");
            //通过设置头信息给文件命名，也即是，在前端，文件流被接受完还原成原文件的时候会以你传递的文件名来命名
            try {
                // 设置文件名 支持中文 采用中文文件名需要在此处转码
                fileName = new String(fileName.getBytes("GBK"), "ISO_8859_1");
                response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            } catch (UnsupportedEncodingException e) {
                log.error("不支持文件返回设置编码", e);
            }
            //进行读写操作
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                //从源文件中读
                int i = bis.read(buffer);
                while (i != -1) {
                    //写到response的输出流中
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (IOException e) {
                log.error("文件流io异常", e);
            } finally {
                //善后工作，关闭各种流
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    log.error("文件流io异常", e);
                }
            }
        } else {
            throw new BusinessException("附件下载失败");
        }
    }

    /**
     * 删除文件或者文件夹
     *
     * @param file
     * @return
     */
    public static boolean delFile(File file) {
        if (!file.exists()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f);
            }
        }
        return file.delete();
    }


    /**
     * 预览图片
     *
     * @param path
     * @param response
     */
    public static void lookFile(String path, String fileName, HttpServletResponse response) {
        if (StringUtils.isBlank(path)) {
            throw new BusinessException("传入参数错误");
        }
        File file = new File(path);
        //当文件存在
        if (file.exists()) {
            //进行读写操作
            FileInputStream fis = null;
            ServletOutputStream out = null;
            try {
                fis = new FileInputStream(file);
                out = response.getOutputStream();
                byte[] content = new byte[1024];
                int length = -1;
                while ((length = fis.read(content)) != -1) {
                    out.write(content, 0, length);
                    out.flush();
                }
            } catch (IOException e) {
                log.error("文件流io异常", e);
            } finally {
                //善后工作，关闭各种流
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    log.error("文件流io异常", e);
                }
            }
        } else {
            throw new BusinessException("预览图片失败");
        }
    }

    /**
     * 生成压缩包
     *
     * @param filePathList
     * @return
     */
    public static String createZipFile(List<String> filePathList) {
        ZipOutputStream out = null;
        // 压缩文件路径
        String zipFilePath = ApplicationContextUtil.getTmpPath() + File.separator + UUID.uuid() + ".zip";
        try {
            // 创建压缩文件
            File zipFile = new File(zipFilePath);
            out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFilePath)));
            try {
                zipFile.createNewFile();
            } catch (IOException e) {
                log.info("创建zip文件失败!");
            }
            for (String compressFilePath : filePathList) {
                // 添加文件到压缩文件中
                File file = new File(compressFilePath);
                if (!file.exists()) {
                    log.info("文件不存在,添加失败!");
                    continue;
                } else {
                    if (file.isFile()) {
                        zipOFile(out, file);
                    }
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage());
        } finally {
            try {
                //关闭输出流
                out.close();
            } catch (IOException e) {
                log.info("关闭流失败!", e);
            }
        }
        return zipFilePath;
    }

    public static void zip(ZipOutputStream zipOutput, File file, String suffixPath) {
        try {
            ZipEntry zEntry = null;
            if ("".equals(suffixPath)) {
                zEntry = new ZipEntry(file.getName());
            } else {
                zEntry = new ZipEntry(suffixPath + File.separator + file.getName());
            }
            zipOutput.putNextEntry(zEntry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int read = 0;
            while ((read = bis.read(buffer)) != -1) {
                zipOutput.write(buffer, 0, read);
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void zipOFile(ZipOutputStream zipOutput, File file) {
        try {
            ZipEntry zEntry = new ZipEntry(file.getName());
            zipOutput.putNextEntry(zEntry);
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int read = 0;
            while ((read = bis.read(buffer)) != -1) {
                zipOutput.write(buffer, 0, read);
            }
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean writeStringToFile(String filePath, String data) {
        PrintStream printStream = null;
        try {
            File file = new File(filePath);
            printStream = new PrintStream(new FileOutputStream(file));
            printStream.println(data);
            printStream.close();
            return true;
        } catch (FileNotFoundException e) {
            return false;
        }
    }


    public static String readFileToString(String filePath) {
        try {
            StringBuilder sb = new StringBuilder("");
            FileReader reader = new FileReader(filePath);
            BufferedReader br = new BufferedReader(reader);
            String str = null;
            while ((str = br.readLine()) != null) {
                sb.append(str + "\r\n");
            }
            br.close();
            reader.close();
            return sb.toString();
        } catch (Exception e) {

        }
        return "";
    }

    public static void main(String[] args) {
        File file = new File("E:\\companyWorkSpace\\financial-api\\data\\tmp\\meshFile");
        delFile(file);
    }

}
